﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    public class UList<T> : IEnumerable<T>
    {
        const int _defaultCapacity = 4;
        static T[] _emptyArray;
        T[] _items;
        int _size;
        [NonSerialized]
        object _syncRoot = new object();
        int _version;

        static UList()
        {
            _emptyArray = new T[0];
        }

        public UList(int size = _defaultCapacity)
        {
            _items = new T[size];
        }
        public int Count { get { return _items.Length; } }

        public void Add(T item)
        {
            lock (_syncRoot)
            {

                if (_size == _items.Length)
                {
                    EnsureCapacity();
                }
                _items[_size++] = item;
                _version++;
            }
        }

        public void Clear()
        {
            if (_size == 0)
            {
                Array.Clear(_items, 0, _size);
                _size = 0;
            }
            _version++;
        }
        public bool Contains(T item)
        {
            if (item == null)
            {
                for (int i = 0; i < _size; i++)
                {
                    if (_items[i] == null)
                    {
                        return true;
                    }
                }
                return false;
            }

            EqualityComparer<T> comparer = EqualityComparer<T>.Default;
            for (int i = 0; i < _size; i++)
            {
                if (comparer.Equals(_items[i], item))
                {
                    return true;
                }
            }
            return false;
        }

        public void CopyTo(T[] array)
        {
            //this.CopyTo(array, 0);
        }
        void EnsureCapacity()
        {
            var t2 = new T[_items.Length * 2];
            for (int i = 0; i < _items.Length; i++)
            {
                t2[i] = _items[i];
            }
            _items = t2;
        }

        public IEnumerator<T> GetEnumerator()
        {
            for (int i = 0; i < _items.Length; i++)
            {
                yield return _items[i];
            }
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return _items.GetEnumerator();
        }

        public int IndexOf(T item)
        {
            return Array.IndexOf<T>(_items, item);
        }

        public bool Remove(T item)
        {
            int index = IndexOf(item);
            if (index >= 0)
            {
                this.RemoveAt(index);
                return true;
            }
            return false;
        }
        public void RemoveAt(int index)
        {
            lock (_syncRoot)
            {
                T[] t2 = new T[_items.Length - 1];
                for (int i = 0; i < t2.Length; i++)
                {
                    if (index > i)
                    {
                        t2[i] = _items[i];
                    }
                    else
                    {
                        t2[i] = _items[i + 1];
                    }
                }
                _items = t2;
            }
            _version++;
        }

        public T this[int index]
        {
            get { return _items[index]; }
        }
    }
}
